#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
Modbus设备模拟器管理类（重构版）
基于pymodbus 3.11.2实现，通过组合独立的模拟器类实现TCP/RTU设备模拟
"""

from datetime import datetime
from typing import Dict, Any, Optional, Callable

from .tcp_simulator import ModbusTcpSimulator
from .rtu_simulator import ModbusRtuSimulator


class ModbusSimulatorManager:
    """
    Modbus设备模拟器管理类
    管理TCP、RTU两种独立的模拟器实例
    """

    def __init__(self, message_callback: Optional[Callable] = None):
        """
        初始化模拟器管理器

        Args:
            message_callback: 消息回调函数，用于向GUI发送消息
        """
        self.callback = message_callback or self._default_callback
        self.simulators: Dict[str, Any] = {}  # {server_id: simulator_instance}
        self.running = True

    def _default_callback(self, message: str, level: str = "INFO", msg_type: str = "normal"):
        """默认回调函数"""
        print(f"[{level}] {message}")

    def _notify(self, message: str, level: str = "INFO", msg_type: str = "normal"):
        """发送通知消息"""
        self.callback(message, level, msg_type)

    # ==================== TCP模拟器 ====================

    def create_tcp_server(self, host: str, port: int, slave_count: int,start_slave_id: int, start_address: int,
                         register_count: int, update_interval: int) -> Optional[str]:
        """
        创建TCP模拟器

        Args:
            host: 监听IP地址
            port: 监听端口
            slave_count: 从站数量
            start_slave_id: 开始从站地址
            start_address: 开始寄存器地址
            register_count: 每个从站的寄存器数量
            update_interval: 数据更新间隔（秒）

        Returns:
            创建的模拟器ID，失败返回None
        """
        server_id = f"tcp_{host}_{port}"

        # 检查是否已存在
        if server_id in self.simulators:
            self._notify(f"❌ TCP模拟器 {host}:{port} 已存在", "ERROR", "error")
            return None

        try:
            # 创建TCP模拟器实例
            simulator = ModbusTcpSimulator(message_callback=self.callback)

            # 配置模拟器
            if not simulator.configure(
                host=host,
                port=port,
                slave_count=slave_count,
                start_slave_id=start_slave_id,
                start_address=start_address,
                register_count=register_count,
                update_interval=update_interval
            ):
                return None

            # 保存模拟器实例
            self.simulators[server_id] = {
                "id": server_id,
                "type": "TCP",
                "simulator": simulator,
                "created_time": datetime.now(),
            }

            self._notify(f"✅ TCP模拟器创建成功: {server_id}", "SUCCESS", "normal")
            return server_id

        except Exception as e:
            self._notify(f"❌ 创建TCP模拟器失败: {e}", "ERROR", "error")
            return None

    # ==================== RTU模拟器 ====================

    def create_rtu_server(self, port: str, baudrate: int, databits: int,
                         parity: str, stopbits: int, slave_count: int, start_slave_id: int, start_address: int,
                         register_count: int, update_interval: int) -> Optional[str]:
        """
        创建RTU模拟器

        Args:
            port: 串口端口
            baudrate: 波特率
            databits: 数据位
            parity: 校验位
            stopbits: 停止位
            slave_count: 从站数量
            start_slave_id: 开始从站地址
            start_address: 开始寄存器地址
            register_count: 每个从站的寄存器数量
            update_interval: 数据更新间隔（秒）

        Returns:
            创建的模拟器ID，失败返回None
        """
        server_id = f"rtu_{port.replace('/', '_')}_{baudrate}"

        # 检查是否已存在
        if server_id in self.simulators:
            self._notify(f"❌ RTU模拟器 {port}@{baudrate} 已存在", "ERROR", "error")
            return None

        try:
            # 创建RTU模拟器实例
            simulator = ModbusRtuSimulator(message_callback=self.callback)

            # 配置模拟器
            if not simulator.configure(
                port=port,
                baudrate=baudrate,
                databits=databits,
                parity=parity,
                stopbits=stopbits,
                slave_count=slave_count,
                start_slave_id=start_slave_id,
                start_address=start_address,
                register_count=register_count,
                update_interval=update_interval
            ):
                return None

            # 保存模拟器实例
            self.simulators[server_id] = {
                "id": server_id,
                "type": "RTU",
                "simulator": simulator,
                "created_time": datetime.now(),
            }
            self._notify(f"✅ RTU模拟器创建成功: {server_id}", "SUCCESS", "normal")
            return server_id

        except Exception as e:
            self._notify(f"❌ 创建RTU模拟器失败: {e}", "ERROR", "error")
            return None

    # ==================== 模拟器控制 ====================

    def start_server(self, server_id: str) -> bool:
        """
        启动指定模拟器

        Args:
            server_id: 模拟器ID

        Returns:
            启动成功返回True，失败返回False
        """
        sim_info = self.simulators.get(server_id)
        if not sim_info:
            self._notify(f"❌ 模拟器 {server_id} 不存在", "ERROR", "error")
            return False

        try:
            simulator = sim_info["simulator"]
            return simulator.start()

        except Exception as e:
            self._notify(f"❌ 启动模拟器 {server_id} 失败: {e}", "ERROR", "error")
            return False

    def stop_server(self, server_id: str) -> bool:
        """
        停止指定模拟器

        Args:
            server_id: 模拟器ID

        Returns:
            停止成功返回True，失败返回False
        """
        sim_info = self.simulators.get(server_id)
        if not sim_info:
            self._notify(f"❌ 模拟器 {server_id} 不存在", "ERROR", "error")
            return False

        try:
            simulator = sim_info["simulator"]
            return simulator.stop()

        except Exception as e:
            self._notify(f"❌ 停止模拟器 {server_id} 失败: {e}", "ERROR", "error")
            return False

    def clear_all_servers(self):
        """停止并清空所有模拟器"""
        if not self.simulators:
            self._notify("📭 没有模拟器需要清空", "INFO", "normal")
            return

        server_count = len(self.simulators)
        self._notify(f"🔄 开始停止并清空 {server_count} 个模拟器...", "INFO", "normal")

        # 先停止所有模拟器
        for server_id in list(self.simulators.keys()):
            self.stop_server(server_id)

        # 清空所有数据
        self.simulators.clear()

        self._notify(f"🗑️ 已停止并清空所有 {server_count} 个模拟器", "SUCCESS", "normal")

    # ==================== 查询方法 ====================

    def get_all_servers(self) -> Dict[str, Dict[str, Any]]:
        """获取所有模拟器信息"""
        return self.simulators.copy()

    def get_server_info(self, server_id: str) -> Optional[Dict[str, Any]]:
        """获取指定模拟器信息"""
        return self.simulators.get(server_id)

    def get_running_servers(self) -> Dict[str, Dict[str, Any]]:
        """获取运行中的模拟器"""
        return {
            server_id: info
            for server_id, info in self.simulators.items()
            if info["simulator"].is_running()
        }

    def get_server_count(self) -> int:
        """获取模拟器总数"""
        return len(self.simulators)

    def get_running_count(self) -> int:
        """获取运行中的模拟器数量"""
        return len(self.get_running_servers())

    def get_client_count(self) -> int:
        """获取客户端连接数（GUI兼容方法）"""
        return self.get_running_count()

    def get_request_count(self) -> int:
        """获取处理请求数（GUI兼容方法）"""
        return self.get_server_count()

    def shutdown(self):
        """关闭模拟器管理器"""
        self.running = False
        self.clear_all_servers()
        self._notify("🔌 模拟器管理器已关闭", "INFO", "normal")

    # ==================== GUI兼容方法 ====================

    def start_tcp_simulator(self, host: str, port: int, device_count: int,
                           start_slave_id: int, start_address: int,
                           end_address: int, update_interval: float) -> bool:
        """
        启动TCP模拟器（GUI兼容方法）

        Args:
            host: 监听IP地址
            port: 监听端口
            device_count: 设备数量
            start_slave_id: 起始从站ID（未使用，为了兼容GUI）
            start_address: 起始地址（未使用，为了兼容GUI）
            end_address: 结束地址（未使用，为了兼容GUI）
            update_interval: 更新间隔

        Returns:
            启动成功返回True，失败返回False
        """
        try:
            # 计算寄存器数量
            register_count = end_address + start_address + 1

            # 创建TCP模拟器
            server_id = self.create_tcp_server(
                host=host,
                port=port,
                slave_count=device_count,
                start_slave_id=start_slave_id,
                start_address=start_address,
                register_count=register_count,
                update_interval=int(update_interval)
            )

            if not server_id:
                return False

            # 启动模拟器
            return self.start_server(server_id)

        except Exception as e:
            self._notify(f"❌ 启动TCP模拟器失败: {e}", "ERROR", "error")
            return False

    def start_rtu_simulator(self, port: str, baudrate: int, bytesize: int,
                           parity: str, stopbits: int, device_count: int,
                           start_slave_id: int, start_address: int,
                           end_address: int, update_interval: float) -> bool:
        """启动RTU模拟器（GUI兼容方法）"""
        try:
            register_count = end_address + start_address + 1

            server_id = self.create_rtu_server(
                port=port,
                baudrate=baudrate,
                databits=bytesize,
                parity=parity,
                stopbits=stopbits,
                slave_count=device_count,
                start_address=start_address,
                start_slave_id=start_slave_id,
                register_count=register_count,
                update_interval=int(update_interval)
            )

            if not server_id:
                return False

            return self.start_server(server_id)

        except Exception as e:
            self._notify(f"❌ 启动RTU模拟器失败: {e}", "ERROR", "error")
            return False

    def stop_simulator(self) -> bool:
        """停止模拟器（GUI兼容方法）"""
        try:
            self.clear_all_servers()
            return True
        except Exception as e:
            self._notify(f"❌ 停止模拟器失败: {e}", "ERROR", "error")
            return False
